package com.ihr360.expr.core;

import com.ihr360.expr.ExprError;
import com.ihr360.expr.ExprException;
import com.ihr360.expr.ExprMissing;
import com.ihr360.expr.context.IEvaluationContext;

import java.math.BigDecimal;

/**
 * 算数运算
 */
public abstract class AbstractMathematicalOperator extends
        AbstractBinaryOperator {
    protected AbstractMathematicalOperator(ExprType type, Expr lhs, Expr rhs) {
        super(type, lhs, rhs);
    }

    protected double evaluateExpr(Expr e, IEvaluationContext context)
            throws ExprException {
        e = eval(e, context);
        if (e == null) {
            return 0;
        }
        if (e instanceof ExprMissing) {
            return 0;
        }
        ExprTypes.assertType(e, ExprType.Integer, ExprType.Double, ExprType.BigDecimal);
        return ((ExprNumber) e).doubleValue();
    }

    @Override
    public Expr evaluate(IEvaluationContext context) throws ExprException {
        Expr l = eval(lhs, context);
        if (l instanceof ExprError) {
            return l;
        }
        Expr r = eval(rhs, context);
        if (r instanceof ExprError) {
            return r;
        }
        return evaluate(evaluateExpr(l, context), evaluateExpr(r, context));
    }

    protected abstract Expr evaluate(double lhs, double rhs)
            throws ExprException;

    protected abstract Expr evaluate(BigDecimal lhs, BigDecimal rhs)
            throws ExprException;
}